package cn.taobaoke.restful.controller;

import cn.taobaoke.restful.exception.TBKException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Comparator;

import static cn.taobaoke.restful.util.Constants.ROBOT_ROOT;
import static cn.taobaoke.restful.util.Constants.ROBOT_ROOT_V2;

/**
 * @author yangzuo
 * @since 2017-05-21 14:10
 */
@RestController
@RequestMapping("/api/files")
public class RobotVersionController extends BaseController {

//    @GetMapping("/robots/versions/latest")
    public Result getLatestVersion() throws IOException {
        Path path = Paths.get(ROBOT_ROOT);
        File file = new File(path.toString());

        String []names = file.list();
        if (names == null) {
            throw new TBKException("Robot Directory Not Exist.");
        }

        String name = Arrays.stream(names).max(Comparator.comparing(String::toString))
                .orElseThrow(() -> new TBKException("No Version"));

        return wrapObj(name);
    }

//    @GetMapping("/robots/versions")
    public Result getVersions() throws IOException {
        Path path = Paths.get(ROBOT_ROOT);
        File file = new File(path.toString());

        String []names = file.list();
        if (names == null) {
            throw new TBKException("Robot Directory Not Exist.");
        }

        return wrapObj(names);
    }

//    @GetMapping("/robots")
    public ResponseEntity<InputStreamResource> downloadRobot(String version, String filename) throws IOException {
        logger.info("GET /api/files/robots?version={}&filename={}", version, filename);
        Path path = Paths.get(ROBOT_ROOT, version, filename);
        FileSystemResource file = new FileSystemResource(path.toString());
        HttpHeaders headers = new HttpHeaders();
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getFilename()));
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");

        return ResponseEntity
                .ok()
                .headers(headers)
                .contentLength(file.contentLength())
                .contentType(MediaType.parseMediaType("application/octet-stream"))
                .body(new InputStreamResource(file.getInputStream()));
    }

    @GetMapping("/v2/robots/versions/latest")
    public Result getLatestVersion(@RequestParam String robotType) {
        Path path = Paths.get(ROBOT_ROOT_V2, robotType);
        File file = new File(path.toString());

        String []names = file.list();
        if (names == null) {
            throw new TBKException("Robot Directory ["+ robotType +"] Does Not Exist.");
        }

        String name = Arrays.stream(names).max(Comparator.comparing(String::toString))
                .orElseThrow(() -> new TBKException("No Version"));

        return wrapObj(name);
    }

    @GetMapping("/v2/robots/versions")
    public Result getVersions(@RequestParam String robotType) {
        Path path = Paths.get(ROBOT_ROOT_V2, robotType);
        File file = new File(path.toString());

        String []names = file.list();
        if (names == null) {
            throw new TBKException("Robot Directory ["+ robotType +"] Does Not Exist.");
        }

        return wrapObj(names);
    }

    @GetMapping("/v2/robots")
    public ResponseEntity<InputStreamResource> downloadRobot(@RequestParam String robotType, @RequestParam String version, String filename) throws IOException {
        logger.info("GET /api/files/robots?robotType={}&version={}&filename={}", robotType, version, filename);

        Path dir = Paths.get(ROBOT_ROOT_V2, robotType, version);
        if (filename == null) {
            filename = getRobotFilename(dir);
        } else {
            Path tmpPath = Paths.get(ROBOT_ROOT_V2, robotType, version, filename);
            if (! Files.exists(tmpPath)) {
                filename = getRobotFilename(dir);
            }
        }

        Path path = Paths.get(ROBOT_ROOT_V2, robotType, version, filename);

        if (!Files.exists(path)) {
            throw new TBKException(robotType + ":" + version + " (No such robot version)");
        }

        FileSystemResource file = new FileSystemResource(path.toString());
        HttpHeaders headers = new HttpHeaders();
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getFilename()));
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");

        return ResponseEntity
                .ok()
                .headers(headers)
                .contentLength(file.contentLength())
                .contentType(MediaType.parseMediaType("application/octet-stream"))
                .body(new InputStreamResource(file.getInputStream()));
    }

    private String getRobotFilename(final Path path) {
        if (! Files.exists(path)) {
            throw new TBKException("No such version " + path.getFileName());
        }
        File file = new File(path.toString());
        String []names = file.list();
        if (names == null) {
            throw new TBKException("No Version File List");
        }

        return Arrays.stream(names).filter(it -> it.endsWith(".exe")).findAny()
                .orElseThrow(() -> new TBKException("No Latest Version File"));
    }

//    @PostMapping("/robots")
//    public Result uploadRobotExe(@RequestParam("file") MultipartFile file, @RequestParam String version) {
//        if (!file.isEmpty()) {
//            String filename = file.getOriginalFilename();
//            logger.info("上传机器人: /api/files/robots name={}, version={}", file.getOriginalFilename(), version);
//
//            try {
//                makeDirectories(version);
//                Files.copy(file.getInputStream(), Paths.get(ROBOT_ROOT, version, filename), StandardCopyOption.REPLACE_EXISTING);
//            } catch (IOException e) {
//                throw new TBKException("Upload Robot Binary Failed.", e);
//            }
//        }
//        return wrapVoid();
//    }
//
//    private void makeDirectories(String version) throws IOException {
//        Path path = Paths.get(ROBOT_ROOT, version);
//        if (!Files.exists(path)) {
//            Files.createDirectories(path);
//        }
//    }

    private static Logger logger = LogManager.getLogger(RobotVersionController.class);
}
